package com.zmn.oms.dubbo.impl.normal.order;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.zmn.base.product.common.dto.product.erp.ProductGroupDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductGroupForeignListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.dto2.data.LayuiTableDO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.pager.Pages;
import com.zmn.cube.common.utils.StringUtil;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.dio.normal.query.GirdOrderWorkQueryDIO;
import com.zmn.oms.common.dro.normal.order.GridOrderWorkDRO;
import com.zmn.oms.common.dro.normal.order.GridOrderWorkServGourpDRO;
import com.zmn.oms.dubbo.interfaces.normal.order.GridOrderWorkListRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.bo.work.EsQueryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：网格工单查询
 *
 * @author heciqi
 * @date 2021/07/20 10:22
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 10000, retries = 0, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class GridOrderWorkListRemoteServiceImpl implements GridOrderWorkListRemoteService {
	@Autowired
	OrderWorkEsBService orderWorkEsBService;
	@Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
	ProductGroupForeignListRemoteService productGroupForeignListRemoteService;

	/**
	 * 查询网格列表
	 *
	 * @param girdOrderWorkQueryDIO
	 * @return
	 */
	@SuppressWarnings("AlibabaRemoveCommentedCode")
	@Override
	public ResponseDTO<LayuiTableDO<GridOrderWorkDRO>> listOrderWork(GirdOrderWorkQueryDIO girdOrderWorkQueryDIO) {
		log.info("网格工单查询，入参：{}", girdOrderWorkQueryDIO);

		BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
				.filter(QueryBuilders.termsQuery("type", Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)))
				.filter(QueryBuilders.termQuery("bizType", girdOrderWorkQueryDIO.getBizType()));
		queryBuilder.mustNot(QueryBuilders.termQuery("gridId",GlobalConsts.NONE));// 排除非网格id的订单

		if (Objects.nonNull(girdOrderWorkQueryDIO.getProvinceId())) {
			queryBuilder.filter(QueryBuilders.termQuery("provinceId", girdOrderWorkQueryDIO.getProvinceId()));
		}
		if (Objects.nonNull(girdOrderWorkQueryDIO.getCityId())) {
			queryBuilder.filter(QueryBuilders.termQuery("cityId", girdOrderWorkQueryDIO.getCityId()));
		}
		if (Objects.nonNull(girdOrderWorkQueryDIO.getCountyId())) {
			queryBuilder.filter(QueryBuilders.termQuery("countyId", girdOrderWorkQueryDIO.getCountyId()));
		}
		if (Objects.nonNull(girdOrderWorkQueryDIO.getManageCompanyId())) {
			queryBuilder.filter(QueryBuilders.termQuery("manageCompanyId", girdOrderWorkQueryDIO.getManageCompanyId()));
		}
		if (Objects.nonNull(girdOrderWorkQueryDIO.getGridManageCompanyId())) {
			queryBuilder.filter(QueryBuilders.termQuery("gridManageCompanyId", girdOrderWorkQueryDIO.getGridManageCompanyId()));
		}
		// 下单时间范围过滤
		if (Objects.nonNull(girdOrderWorkQueryDIO.getReceiveStartTime()) || Objects.nonNull(girdOrderWorkQueryDIO.getReceiveEndTime())) {
			RangeQueryBuilder receiveTimeRange = QueryBuilders.rangeQuery("receiveTime");
			if (Objects.nonNull(girdOrderWorkQueryDIO.getReceiveStartTime())) {
				receiveTimeRange.gte(DateUtil.toString(girdOrderWorkQueryDIO.getReceiveStartTime()));
			}
			if (Objects.nonNull(girdOrderWorkQueryDIO.getReceiveEndTime())) {
				receiveTimeRange.lte(DateUtil.toString(girdOrderWorkQueryDIO.getReceiveEndTime()));
			}
			queryBuilder.filter(receiveTimeRange);
		}
		// 经纬度范围过滤
		if (StringUtil.isNotBlank(girdOrderWorkQueryDIO.getGirdPolygon())) {
			try {
				String[] arrPonit = girdOrderWorkQueryDIO.getGirdPolygon().split(",");
				List<GeoPoint> geoCoordinates = Lists.newArrayListWithCapacity(arrPonit.length);
				for (String s : arrPonit) {
					String[] xy = s.trim().split(" ");// StringUtils.replace(, " ", ",");
					geoCoordinates.add(new GeoPoint(Double.valueOf(xy[0]), Double.valueOf(xy[1])));
				}
				/*PolygonBuilder polygonBuilder = ShapeBuilders.newPolygon(geoCoordinates);
				GeoShapeQueryBuilder filter;
				filter = QueryBuilders.geoShapeQuery("contact.locationShape", polygonBuilder);
				filter.relation(ShapeRelation.WITHIN);
				queryBuilder.filter(filter);*/
				GeoPolygonQueryBuilder filter = QueryBuilders.geoPolygonQuery("contact.locationShape", geoCoordinates);
				queryBuilder.filter(filter);
			}catch (Exception e) {
				log.error(e.getMessage(), e);
			}
		}

		NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
		searchQuery.setPageable(EsQueryBuilder.getPageRequest(girdOrderWorkQueryDIO));
		String groupFiled = "gridId";
		// 网格分组
		TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(groupFiled)
				.field(groupFiled);
		// 产品分组-分组
		TermsAggregationBuilder servAggregationProductBuilder = AggregationBuilders.terms("servProductGroupId")
				.field("servProductGroupId");
		termsAggregationBuilder.subAggregation(servAggregationProductBuilder);
		searchQuery.addAggregation(termsAggregationBuilder);

		// 500条
		termsAggregationBuilder.size(500);
		if (Objects.equals(Pages.DEFAULT_ORDER_YES, girdOrderWorkQueryDIO.getDefaultOrder())) {
			termsAggregationBuilder.order(BucketOrder.count(false));
		} else {
			if (StringUtil.isNotBlank(girdOrderWorkQueryDIO.getOrderDirection())) {
				boolean isAsc = Objects.equals(girdOrderWorkQueryDIO.getOrderDirection(), Pages.ORDER_DIRECTION_ASC);
				termsAggregationBuilder.order(BucketOrder.count(isAsc));
			}
		}

		log.info("网格查询es===>{}",queryBuilder.toString());
		Aggregations query1 = orderWorkEsBService.getAggregationsByQuery(searchQuery);
		ParsedLongTerms terms = query1.get(groupFiled);
		List<? extends Terms.Bucket> buckets = terms.getBuckets();
		if (CollectionUtils.isEmpty(buckets)) {
			LayuiTableDO layuiTableDO = new LayuiTableDO();
			layuiTableDO.setCount(0);
			layuiTableDO.setData(Collections.emptyList());
			return ResponseDTO.success(layuiTableDO);
		}

		List<GridOrderWorkDRO> list = Lists.newArrayList();
		Set<Integer> servProductGroups = Sets.newHashSet();
		buckets.forEach(bucket -> {
			Map<String, Aggregation> stringAggregationMap = bucket.getAggregations().asMap();
			// 网格
			GridOrderWorkDRO gridOrderWorkDRO = new GridOrderWorkDRO();
			gridOrderWorkDRO.setGridId(Integer.valueOf(bucket.getKeyAsString()));
			gridOrderWorkDRO.setCount(bucket.getDocCount());
			// 产品分组
			List<GridOrderWorkServGourpDRO> servGourpDROS = Lists.newArrayList();
			ParsedLongTerms servProuctGroupTerms = (ParsedLongTerms) stringAggregationMap.get("servProductGroupId");
			List<? extends Terms.Bucket> servProuctGroup = servProuctGroupTerms.getBuckets();
			log.info("servProuctGroup.size:{}", servProuctGroup);
			servProuctGroup.forEach(servProuctGroupBucket -> {
				Integer servProductGroupId = Integer.valueOf(servProuctGroupBucket.getKeyAsString());
				GridOrderWorkServGourpDRO gridOrderWorkServGourpDRO = new GridOrderWorkServGourpDRO();
				gridOrderWorkServGourpDRO.setServProductGroupId(servProductGroupId);
				gridOrderWorkServGourpDRO.setCount(servProuctGroupBucket.getDocCount());
				servGourpDROS.add(gridOrderWorkServGourpDRO);
				servProductGroups.add(servProductGroupId);
			});
			gridOrderWorkDRO.setGridServGourpDROS(servGourpDROS);
			list.add(gridOrderWorkDRO);
		});

		// 补全产品分组名称
		ResponseDTO<List<ProductGroupDRO>> listResponseDTO = productGroupForeignListRemoteService.listByGroupIdsAndStatus(new ArrayList<>(servProductGroups), GlobalConsts.YES);
		log.info("查询分组入参{}，出参{}",servProductGroups,JSON.toJSONString(listResponseDTO));
		if (listResponseDTO.getData() != null) {
			Map<Integer, String> groupMap = listResponseDTO.getData().stream().collect(Collectors.toMap(ProductGroupDRO::getGroupId, ProductGroupDRO::getName));
			for (GridOrderWorkDRO gridOrderWorkDRO : list) {
				for (GridOrderWorkServGourpDRO gridOrderWorkServGourpDRO : gridOrderWorkDRO.getGridServGourpDROS()) {
					if (Objects.nonNull(gridOrderWorkServGourpDRO.getServProductGroupId())) {
						gridOrderWorkServGourpDRO.setServProductGroupName(StringUtils.defaultString(groupMap.get(gridOrderWorkServGourpDRO.getServProductGroupId())));
					} else {
						gridOrderWorkServGourpDRO.setServProductGroupName("");
					}
				}
			}
		}

		LayuiTableDO layuiTableDO = new LayuiTableDO();
		layuiTableDO.setCount(list.size());
		layuiTableDO.setData(list);
		log.info("网格工单查询，返回：{}", layuiTableDO);
		return ResponseDTO.success(layuiTableDO);
	}

}
